package datastructure.book.tujiesuanfa.string._1_easy;

import org.junit.jupiter.api.Test;

import java.util.*;

public class Solution1 {
    /**
     * 将字符串中的'.'替换为' '
     * 输入：path = "a.aef.qerf.bb"
     * 输出："a aef qerf bb"
     */
    public String pathEncryption(String path) {
        if (path == null || path.isEmpty()) {
            return path;
        }
        char[] chars = new char[path.length()];
        for (int i = 0; i < path.length(); i++) {
            if (path.charAt(i) == '.') {
                chars[i] = ' ';
            } else {
                chars[i] = path.charAt(i);
            }
        }
        return new String(chars);
    }

    /**
     * 输入: message = "  hello   world!  "
     * 输出: "world! hello"
     */
    public String reverseMessage(String message) {
        if (message == null || message.isEmpty()) {
            return message;
        }
        StringBuilder sb = new StringBuilder();
        LinkedList<String> resultList = new LinkedList<>();
        for (int i = 0; i < message.length(); i++) {
            if (message.charAt(i) == ' ') {
                if (sb.length() != 0) {
                    resultList.addFirst(sb.toString());
                    sb.setLength(0);
                }
            } else {
                sb.append(message.charAt(i));
            }
        }
        if (sb.length() != 0) {
            resultList.addFirst(sb.toString());
            sb.setLength(0);
        }
        if (resultList.isEmpty()) {
            return "";
        }
        for (int i = 0; i < resultList.size()-1; i++) {
            String s = resultList.get(i);
            sb.append(s).append(" ");
        }
        sb.append(resultList.get(resultList.size()-1));
        return sb.toString();
    }

    @Test
    public void testReverseMessage2(){
        System.out.println(reverseMessage2("  hello world!  "));
        System.out.println(reverseMessage2(" "));
    }
    public String reverseMessage2(String message) {
        if (message == null || message.isEmpty()) {
            return message;
        }
        StringBuilder sb = new StringBuilder();
        int j=message.length()-1;
        for (int i = message.length()-1; i >= 0; i--) {
            if (message.charAt(i) == ' ') {
                if (i != j) {
                    sb.append(message, i + 1, j + 1).append(" ");
                    j = i;
                }
                j--;
            }
        }
        if (j >= 0) {
            sb.append(message, 0, j + 1);
        } else {
            if (sb.length() != 0) {
                sb.deleteCharAt(sb.length()-1);
            }
        }
        return sb.toString();
    }

    /**
     * 将 password 前 target 个字符按原顺序移动至字符串末尾
     * 1 <= target < password.length <= 10000
     * 输入: password = "s3cur1tyC0d3", target = 4
     * 输出: "r1tyC0d3s3cu"
     */
    public String dynamicPassword(String password, int target) {
        if (password == null || password.isEmpty() || target >= password.length()) {
            return password;
        }
        return password.substring(target) + password.substring(0, target);
    }

    @Test
    public void testMyAtoi(){
        System.out.println(myAtoi("-2147483648"));
    }

    /**
     * 不使用库函数的字符串转整数，结果为32位有符号整数
     * 小于 −2^31 的整数应该被固定为 −2^31 ，大于 2^31 − 1 的整数应该被固定为 2^31 − 1 。
     * 读入下一个字符，直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
     * 例如："123" -> 123， "0032" -> 32，"  -12345whis 22 " -> -12345
     */
    public int myAtoi(String str) {
        if (str == null || str.isEmpty()) {
            return 0;
        }
        Character[] number = {'1','2','3','4','5','6','7','8','9','0'};
        ArrayList<Character> numberList = new ArrayList<>(Arrays.asList(number));
        boolean isSmallZero = false;
        Integer start = null; int length = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (numberList.contains(c)) {
                start = i;
                break;
            }
            if ((c == '+' || c == '-') && (i != str.length() - 1) && numberList.contains(str.charAt(i + 1))) {
                start = i+1;
                if (c == '-') {
                    isSmallZero = true;
                }
                break;
            }
            if (c == ' ') {
                continue;
            }
            break;
        }
        if (start == null) {
            return 0;
        }
        for (int i = start; i < str.length(); i++) {
            char c = str.charAt(i);
            if (numberList.contains(c)) {
                if (c == '0' && length == 0) {
                    start++;
                } else {
                    length++;
                }
            } else {
                break;
            }
        }
        double count = 0;
        for (int i = 0; i < length; i++) {
            char c = str.charAt(i + start);
            double num = 0;
            switch (c) {
                case '0':num = 0;break;
                case '1':num = 1;break;
                case '2':num = 2;break;
                case '3':num = 3;break;
                case '4':num = 4;break;
                case '5':num = 5;break;
                case '6':num = 6;break;
                case '7':num = 7;break;
                case '8':num = 8;break;
                case '9':num = 9;break;
            }
            double pow = Math.pow(10, length-i-1);
            if (outOfBound(isSmallZero, pow)) {
                if (isSmallZero) {
                    return Integer.MIN_VALUE;
                } else {
                    return Integer.MAX_VALUE;
                }
            }
            num = num*pow;
            if (outOfBound(isSmallZero, num)) {
                if (isSmallZero) {
                    return Integer.MIN_VALUE;
                } else {
                    return Integer.MAX_VALUE;
                }
            }
            count+=num;
            if (outOfBound(isSmallZero, count)) {
                if (isSmallZero) {
                    return Integer.MIN_VALUE;
                } else {
                    return Integer.MAX_VALUE;
                }
            }
        }
        if (isSmallZero) {
            return -(int)count;
        } else {
            return (int) count;
        }
    }

    public static boolean outOfBound(boolean isSmallZero,double number){
        if (isSmallZero) {
            return number >= (-(double) Integer.MIN_VALUE);
        } else {
            return number >= Integer.MAX_VALUE;
        }
    }

    /**
     * TODO:
     * 有效数字（按顺序）可以分成以下几个部分：
     * 1、若干空格
     * 2、一个 小数 或者 整数
     * 3、（可选）一个 'e' 或 'E' ，后面跟着一个 整数
     * 4、若干空格
     * 小数（按顺序）可以分成以下几个部分：
     *      （可选）一个符号字符（'+' 或 '-'）
     *      下述格式之一：
     *          至少一位数字，后面跟着一个点 '.'
     *          至少一位数字，后面跟着一个点 '.' ，后面再跟着至少一位数字
     *          一个点 '.' ，后面跟着至少一位数字
     * 整数（按顺序）可以分成以下几个部分：
     *      （可选）一个符号字符（'+' 或 '-'）
     *       至少一位数字
     * 举例：
     * 有效数字：["2", "0089", "-0.1", "  +3.14"  , "4.", "  -.9  ", "2e10", "  -90E3  ",
     *          "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
     * 无效数字：["abc", "1e", "e3", "99e2.5", "--6", "-+3", "95  54e53", ".0e" ,"0.e"]
     */
    public boolean validNumber(String s) {
        if (s == null || s.isEmpty()) {
            return false;
        }
        int[][] states = {
                //' ', +, d, ., e
                {   0, 1, 2, 3, 9  },//' '
                {   9, 9, 2, 3, 9  },//+
                {   8, 9, 2, 4, 5  },//d
                {   9, 9, 4, 9, 9  },//' '->.,+->.,.
                {   8, 9, 4, 9, 5  },//.->d,d->.
                {   9, 6, 7, 9, 9  },//e
                {   9, 9, 7, 9, 9  },//+
                {   8, 9, 7, 9, 9  },//d
                {   8, 9, 9, 9, 9  },//' '
                {   9, 9, 9, 9, 9  }//error
        };
        boolean[] validState = {false,false,true,false,true,false,false,true,true,false};
        int state = 0;
        int charIndex;
        for (char c : s.toCharArray()) {
            if (c == ' ') {
                charIndex = 0;
            } else if (c == '+' || c == '-') {
                charIndex = 1;
            } else if (c >= '0' && c <= '9') {
                charIndex = 2;
            } else if (c == '.') {
                charIndex = 3;
            } else if (c == 'e' || c == 'E') {
                charIndex = 4;
            } else {
                return false;
            }
            state = states[state][charIndex];
            if (state == 9) {
                return false;
            }
        }
        return validState[state];
    }
}
